//
//  Date+ZZ.swift
//  KeDaLeDaoHang
//
//  Created by 陈钟 on 2019/6/12.
//  Copyright © 2019 陈钟. All rights reserved.
//

import UIKit
import Foundation

public extension Date{
    
    static func comps(type:Calendar.Component, date: Date = Date()) -> Int {
        let calender = Calendar.init(identifier: .gregorian)
        let comps = calender.component(type, from: date)
        return comps
    }
    
    static func year(date: Date = Date()) -> Int{
        return Date.comps(type: .year, date: date)
    }
    static func month(date: Date = Date()) -> Int{
        return Date.comps(type: .month, date: date)
    }
    static func day(date: Date = Date()) -> Int{
        return Date.comps(type: .day, date: date)
    }
    static func hour(date: Date = Date()) -> Int{
        return Date.comps(type: .hour, date: date)
    }
    static func minute(date: Date = Date()) -> Int{
        return Date.comps(type: .minute, date: date)
    }
    static func second(date: Date = Date()) -> Int{
        return Date.comps(type: .second, date: date)
    }
    static func weekday(date: Date = Date()) -> Int{
        return Date.comps(type: .weekday, date: date)
    }
    
    static func today(_ formatter:String) -> String{
        return ZZTool.dateString(date: Date(), formatter: formatter)
    }
    
    static func today() -> Date{
        let dateStr = ZZTool.dateString(date: Date(), formatter: "yyyy-MM-dd HH:mm:ss")
        return ZZTool.getDate(dateString: dateStr, formatter: "yyyy-MM-dd HH:mm:ss")
    }
    
    /// 一个月有多少天
    func monthTotalDays(calendar: Calendar = Calendar.current) -> Int{
        let daysInMonth = calendar.range(of: .day, in: .month, for: self)
        return daysInMonth?.count ?? 0
    }
    
    /// 根据date获取偏移指定天数的date year = 1表示1年后的时间 year = -1为1年前的日期，month day 类推
    func year(offset: Int, calendar: Calendar = Calendar.current) -> Date?{
        var comps = DateComponents()
        comps.year = offset
        let date = calendar.date(byAdding: comps, to: self)
        return date
    }
    
    /// 根据date获取偏移指定月数的date year = 1表示1年后的时间 year = -1为1年前的日期，month day 类推
    func month(offset: Int, calendar: Calendar = Calendar.current) -> Date?{
        var comps = DateComponents()
        comps.month = offset
        let date = calendar.date(byAdding: comps, to: self)
        return date
    }
    
    /// 根据date获取偏移指定天数的date year = 1表示1年后的时间 year = -1为1年前的日期，month day 类推
    func day(offset: Int, calendar: Calendar = Calendar.current) -> Date?{
        var comps = DateComponents()
        comps.day = offset
        let date = calendar.date(byAdding: comps, to: self)
        return date
    }
    
    /// 将Date转成字符串
    func dateString(with formatterStr: String, calendar: Calendar.Identifier? = nil) -> String{
        let formatter = DateFormatter()
        if let calend = calendar{
            formatter.calendar = Calendar(identifier: calend)
        }
        formatter.dateFormat = formatterStr
        return formatter.string(from: self)
    }
    
    /// 字符串转Date
    static func date(with dateStr: String, formatter: String = "yyyy-MM-dd", calendar: Calendar.Identifier? = nil) -> Date?{
        let dateFormatter = DateFormatter()
        if let calend = calendar{
            dateFormatter.calendar = Calendar(identifier: calend)
        }
        dateFormatter.dateFormat = formatter
        return dateFormatter.date(from: dateStr)
    }
    
    /// 判断两个时间年月日是否相等
    func equal(day: Date) -> Bool{
        return self.year == day.year && self.month == day.month && self.day == day.day
    }
    
    /// 年
    var year: String {
        return dateString(with: "yyyy")
    }
    
    /// yue
    var month: String {
        return dateString(with: "MM")
    }
    
    /// 日
    var day: String {
        return dateString(with: "dd")
    }
    
    /// 小时
    var hour: String {
        return dateString(with: "HH")
    }
    
    /// 分
    var minute: String {
        return dateString(with: "mm")
    }
    
    /// 秒
    var seconds: String {
        return dateString(with: "ss")
    }
    
    /// 星期几
    var weekDay: Int{
        let interval = self.timeIntervalSince1970;
        let days = Int(interval / 86400);
        return (days - 3) % 7;
    }
    
    /// 当前时间是否是今天
    var isToday: Bool{
        return equal(day: Date())
    }
    
    /// 时间戳  精确到毫秒
    var timeStamp: TimeInterval{
        let timeInterval = self.timeIntervalSince1970
        let millisecond = CLongLong(round(timeInterval * 1000))
        return TimeInterval(millisecond)
    }
    
    /// 时间戳转时间
    /// - Parameters:
    ///   - timeStamp: 时间戳
    ///   - formatter: 转换的时间格式
    ///   - calendar: 转换的日历标识 Calendar.Identifier
    /// - Returns: 时间字符串
    static func timeStamp(_ timeStamp: TimeInterval, to formatter: String = "yyyy-MM-dd", calendar: Calendar.Identifier? = nil) -> String{
        let date = Date(timeIntervalSince1970: timeStamp)
        return date.dateString(with: formatter, calendar: calendar)
    }
    
    private static let chineseMonthsArr = ["正", "二", "三", "四", "五", "六", "七", "八", "九", "十", "十一", "腊"]
    /// 农历月
    var chineseMonth: String{
        let cheseMonthNum = dateString(with: "MM", calendar: Calendar.Identifier.chinese)
        return "\(Date.chineseMonthsArr[cheseMonthNum.intValue() - 1])月"
    }
    
    private static let chineseDaysArr = ["初一", "初二", "初三", "初四", "初五", "初六", "初七", "初八", "初九", "初十",
                          "十一", "十二", "十三", "十四", "十五", "十六", "十七", "十八", "十九", "二十",
                          "廿一", "廿二", "廿三", "廿四", "廿五", "廿六", "廿七", "廿八", "廿九", "三十", ]
    /// 农历日
    var chineseDay: String{
        let chineseDayNum = dateString(with: "dd", calendar: Calendar.Identifier.chinese)
        return "\(Date.chineseDaysArr[chineseDayNum.intValue() - 1])"
        
    }
    
    /// 时辰
    var chineseHour: String{
        let startTime = "\(year)-\(month)-\(day) 00:00:00"
        let startTimeDate = Date.date(with: startTime, formatter: "yyyy-MM-dd HH:mm:ss")
        let startTimeStamp = (startTimeDate?.timeStamp ?? 0) / 1000
        let nowTimeStamp = timeStamp / 1000
        
        let timeSpace = (nowTimeStamp - startTimeStamp) / 60 / 60

        switch timeSpace{
            case 1 ... 3:
                return "丑时"
            case 3 ... 5:
                return "寅时"
            case 5 ... 7:
                return "卯时"
            case 7 ... 9:
                return "辰时"
            case 9 ... 11:
                return "巳时"
            case 11 ... 13:
                return "午时"
            case 13 ... 15:
                return "未时"
            case 15 ... 17:
                return "申时"
            case 17 ... 19:
                return "酉时"
            case 19 ... 21:
                return "戌时"
            case 21 ... 23:
                return "亥时"
            default: return "子时"
        }
    }
}
